/**
 * OrderDaoImpl.java
 * 
 * Copyright@2015 OVT Inc. All rights reserved. 
 * 
 * 2015年12月21日
 */
package com.ovt.order.dao;

import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.text.MessageFormat;
import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.BatchPreparedStatementSetter;
import org.springframework.stereotype.Repository;

import com.ovt.order.dao.contant.OrderState;
import com.ovt.order.dao.handler.PostSaveHandler;
import com.ovt.order.dao.mapper.OrderItemMapper;
import com.ovt.order.dao.mapper.OrderMapper;
import com.ovt.order.dao.vo.Order;
import com.ovt.order.dao.vo.OrderItem;

/**
 * OrderDaoImpl
 * 
 * @Author brad.zhou
 * @Version 1.0
 * @See
 * @Since [OVT Cloud Platform]/[API] 1.0
 */
@Repository
public class OrderDaoImpl implements OrderDao
{

    @Autowired
    private DaoHelper daoHelper;

    @Autowired
    private OrderMapper orderMapper;

    @Autowired
    private OrderItemMapper orderItemMapper;

    public static final String SQL_INSERT_ORDER = "INSERT INTO ORDER(order_no, "
            + "order_state, order_total_fee,"
            + "user_id, order_remark, is_delete,"
            + "create_time, update_time) "
            + "VALUES(?, ?, ?, ?, ?, ?, CURRENT_TIMESTAMP, CURRENT_TIMESTAMP)";

    public static final String SQL_INSERT_ORDERITEM = "INSERT INTO ORDERITEM(order_id, "
            + "item_no, item_name, item_price, item_num)"
            + "VALUES(?, ?, ?, ?, ?)";

    public static final String SQL_GET_ORDER_PERFIX = "SELECT id, order_no, order_state, order_total_fee, user_id, "
            + "create_time, update_time, order_remark, is_delete FROM order";

    public static final String SQL_GET_ORDER = SQL_GET_ORDER_PERFIX
            + "WHERE is_delete = 0 AND order_no = ?";

    public static final String SQL_GET_ORDER_LIST = SQL_GET_ORDER_PERFIX
            + "WHERE is_delete = 0 AND user_id = ?";

    public static final String SQL_UPDATE_ORDER_STATE = "UPDATE order SET order_state = ?, update_time = CURRENT_TIMESTAMP"
            + "WHERE is_delete = 0 AND order_no = ?";

    public static final String SQL_UPDATE_DELETE_FLAG = "UPDATE order SET is_delete = ?, update_time = CURRENT_TIMESTAMP"
            + "WHERE is_delete = 0 AND order_no = ?";

    public static final String SQL_GET_ORDERITEM_LIST = "SELECT id, order_id, item_no, item_name, item_price, item_num "
            + "FROM order_item WHERE order_id = ?";

    @Override
    public long saveOrder(final Order order)
    {
        Object[] params = new Object[6];
        params[0] = order.getOrderNo();
        params[1] = order.getOrderState().toString();
        params[2] = order.getOrderTotalFee();
        params[3] = order.getUserId();
        params[4] = order.getOrderRemark();
        params[5] = order.getIsDelete();

        // final long createTime = System.currentTimeMillis();

        PostSaveHandler handler = new PostSaveHandler()
        {

            @Override
            public void handle(Long Id)
            {
                order.setId(Id);

                // order.setCreateTime(new Timestamp(createTime));
                // order.setUpdateTime(new Timestamp(createTime));

                // put into cache
                // order

            }
        };

        String errMsg = MessageFormat.format(
                "Failed insert order, orderNo={0}!", order.getOrderNo());

        daoHelper.save(SQL_INSERT_ORDER, handler, errMsg, true, params);

        final List<OrderItem> orderItems = order.getOrderItemList();

        // insert orderItems that belong to the order into DB.
        daoHelper.saveBatch(SQL_INSERT_ORDERITEM,
                "Failed to insert orderItem!",
                new BatchPreparedStatementSetter()
                {

                    @Override
                    public void setValues(PreparedStatement ps, int i)
                            throws SQLException
                    {
                        OrderItem orderItem = orderItems.get(i);
                        ps.setLong(1, order.getId());
                        ps.setString(2, orderItem.getProductNo());
                        ps.setString(3, orderItem.getProductName());
                        ps.setFloat(4, orderItem.getProductPrice());
                        ps.setInt(5, orderItem.getProductNum());
                    }

                    @Override
                    public int getBatchSize()
                    {
                        return orderItems.size();
                    }
                });

        return order.getId();
    }

    @Override
    public List<Order> getOrderList(long userId)
    {
        String errMsg = MessageFormat.format(
                "Failed to query orders list which belong to userId={0}!",
                userId);
        List<Order> orders = daoHelper.queryForList(SQL_GET_ORDER_LIST,
                orderMapper, errMsg, userId);

        // Add orderItems to order in orders.
        for (Order order : orders)
        {
            long orderId = order.getId();
            List<OrderItem> orderItems = getOrderItemList(orderId);
            order.setOrderItemList(orderItems);
        }

        return orders;
    }

    @Override
    public Order getOrderInfo(String orderNo)
    {
        if (orderNo == null || orderNo.equals(""))
        {
            return null;
        }

        String errMsg = MessageFormat.format(
                "Failed to query order by orderNo {0}!", orderNo);
        Order order = daoHelper.queryForObject(SQL_GET_ORDER, orderMapper,
                errMsg, orderNo);

        long orderId = order.getId();
        List<OrderItem> orderItems = getOrderItemList(orderId);
        order.setOrderItemList(orderItems);

        return order;
    }

    @Override
    public OrderState updateOrderState(String orderNo, OrderState state)
    {
        Object[] params = new Object[2];
        params[0] = state.toString();
        params[1] = orderNo;

        String errMsg = MessageFormat.format(
                "Failed to update order [{0}] state!", orderNo);
        daoHelper.update(SQL_UPDATE_ORDER_STATE, null, errMsg, params);

        return state;
    }

    @Override
    public int updateOrderDeleteFlag(String orderNo, int flag)
    {
        Object[] params = new Object[2];
        params[0] = flag;
        params[1] = orderNo;

        String errMsg = MessageFormat.format(
                "Failed to update order [{0}] delete flag!", orderNo);
        daoHelper.update(SQL_UPDATE_DELETE_FLAG, null, errMsg, params);

        return flag;
    }

    private List<OrderItem> getOrderItemList(long orderId)
    {
        String errMsg = MessageFormat.format(
                "Failed to query OrderItem list which belong to orderId={0}!",
                orderId);
        List<OrderItem> orders = daoHelper.queryForList(SQL_GET_ORDERITEM_LIST,
                orderItemMapper, errMsg, orderId);

        return orders;
    }

}
